package com.fufu.algorithem.stack;

import java.util.Arrays;
import java.util.List;
import java.util.Stack;
import java.util.function.Consumer;

/**
 * 逆波兰表达式(后缀表达式)Reverse Polish Notation
 * @author: BlcakTiger
 * @date: 2023/2/13 19:48
 * @contact: hsf6661@163.com
 */
public class RPN {

    public static void main(String[] args) {
        //逆波兰表达式 "5 3 + 12 * 7 - 2 +" -》中缀表达式 (5 + 3) * 12 - 7 + 2  res=91
        //测试  "3 4 + 5 * 6 -" -》 中缀表达式 (3 + 4) * 5 - 6   res=29
        //String suffix = "4 5 * 8 - 60 + 8 2 / +"; // (4*5-8+60)+(8/2)

        //创建一个后缀表达式
        String suffix = "10 6 9 3 + -11 * / 17 + 5 +";
        double res = reversePolishCalculator(suffix);
        System.out.println("res:"+String.format("%.2f",res));
    }

    /**
     * 逆波兰计算器
     * @return 返回逆波兰表达式的值
     */
    public static double reversePolishCalculator(String expression){
        //将表达式拆分成数组
        String[] s = expression.split(" ");
        //将数组转换成集合
        List<String> list = Arrays.asList(s);
        //创建栈
        Stack<String> stack = new Stack();
        double num1;
        double num2;
        //正则表达式：1-n位数字
        String mi_regex = "-\\d+";
        String po_regex = "\\d+";
        String pofRegex = "\\d+.\\d+";
        String mifRegex = "-\\d+.\\d+";
        //添加元素到栈中
        for (String s1 : list) {
            //如果是数字
            if (s1.matches(po_regex) || s1.matches(mi_regex) || s1.matches(pofRegex) || s1.matches(mifRegex)) {
                stack.push(s1);
            }else{//操作符
                num1 = Double.parseDouble(stack.pop());
                num2 = Double.parseDouble(stack.pop());
                stack.push(""+calc(num2,num1,s1));
            }
        }
        return Double.parseDouble(stack.pop());
    }

    public static double calc(double n,double m,String op){
        switch (op){
            case "+":
                return n + m;
            case "-":
                return n - m;
            case "*":
                return n * m;
            case "/":
                return n / m;
            default:
                return -1;
        }
    }
}
